package com.why.connector;


import com.why.configurebean.DefaultConfiguration;
import com.why.configurebean.MapperStatement;
import com.why.configurebean.SormProperties;
import com.why.connector.factory.DefualtSqlSessionFactory;
import com.why.connector.factory.SqlSessionFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Properties;

/**
 * 完成配置文件的读取  构建sqlSessionFactory
 *
 * @author wanghongyang24
 */
public class SqlSessionFactoryBuilder {
    private static final Logger logger = LoggerFactory.getLogger(SqlSessionFactoryBuilder.class);
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 完成配置文件的加载
     *
     * @param inputStream
     * @return
     */
    public synchronized SqlSessionFactory build(InputStream inputStream) {
        if (sqlSessionFactory != null) {
            return sqlSessionFactory;
        }
        DefaultConfiguration configuration = null;
        SAXReader docRead = new SAXReader();
        Document document = null;
        try {
            document = docRead.read(inputStream);
            Element element = document.getRootElement();
            Element properties = element.element("properties");
            String resource = properties.attributeValue("resource");
            logger.info("开始加载sormProperties");
            SormProperties sormProperties = this.loadSormProperties(resource, configuration);
            configuration = new DefaultConfiguration(sormProperties);
            logger.info("开始处理xml配置文件");
            Iterator<Element> mappers = element.elementIterator("mappers");
            while (mappers.hasNext()) {
                Element mapper = mappers.next().element("mapper");
                String mapperLocation = mapper.attributeValue("resource");
                loadMapperStatement(configuration, mapperLocation);
            }
            logger.info("所有xml解析完成！");
            sqlSessionFactory = new DefualtSqlSessionFactory(configuration);
            return sqlSessionFactory;
        } catch (DocumentException e) {
            logger.info("解析xml文件过程出现了问题");
            e.printStackTrace();
        } catch (IOException e) {
            logger.info("IO异常");
            e.printStackTrace();
        } catch (Exception e) {
            logger.info("其他未知异常");
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                logger.info("关闭输入输出流失败");
                e.printStackTrace();
            }
        }

        return null;

    }

    /**
     * 加载配置文件 加载默认的configuration
     *
     * @param resource
     * @param configuration
     * @return
     * @throws IOException
     */
    private SormProperties loadSormProperties(String resource, DefaultConfiguration configuration) throws IOException {
        InputStream stream = this.getClass().getClassLoader().getResourceAsStream(resource);
        logger.info("开始加载配置jdbc配置文件");
        Properties properties = new Properties();
        properties.load(stream);
        String userName = properties.getProperty("username");
        String passWord = properties.getProperty("password");
        String url = properties.getProperty("jdbc.url");
        String driver = properties.getProperty("driver");
        logger.info("获取到配置文件的信息为{},{},{},{}" ,userName, passWord, url, driver);
        SormProperties sormProperties = new SormProperties(userName, passWord, url, driver);
        logger.info("成功加载sormProperties");


        return sormProperties;
    }


    /**
     * 加载mapper文件
     *
     * @param configuration
     * @param mapperPath
     * @throws DocumentException
     */
    private void loadMapperStatement(DefaultConfiguration configuration, String mapperPath) throws DocumentException {
        SAXReader docRead = new SAXReader();
        InputStream mapper = this.getClass().getClassLoader().getResourceAsStream(mapperPath);
        Document document = docRead.read(mapper);
        Element rootElement = document.getRootElement();
        String namespace = rootElement.attributeValue("namespace");
        logger.info("获取到的类为{}", namespace);
        logger.info("开始加载Mapper");
        StringBuilder builder = new StringBuilder();
        for (Element element : rootElement.elements()) {

            String methodName = element.attributeValue("id");
            builder.append(namespace).append(".").append(methodName);
            String resultType = element.attributeValue("resultType");
            String jdbcType = element.attributeValue("jdbcType");
            String sql = element.getText();
            logger.info("解析xml获取到的参数:{},{},{},{}",methodName,resultType,jdbcType,sql);
            MapperStatement statement = new MapperStatement(sql, builder.toString(), jdbcType, resultType);
            configuration.addMapper(statement);
            builder.setLength(0);
        }
    }

}
